/**
*@author AL RUBI M. , BONY T. , NANCY S.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include "projv2.h"

void traitementSepia(const pixel tab[], pixel tabRes[], unsigned int largeur, unsigned int hauteur, unsigned int p)
{
	g_printf("Traitement Sepia \n");
    int i, moy, tmpRed, tmpGreen, tmpBlue;
    for (i = 0; i < (largeur*hauteur); i++)
    {
		moy=(tab[i].red+tab[i].green+tab[i].blue)/3;

		tmpRed = moy-2*p;
		tmpGreen = moy-p;
		tmpBlue = moy+3*p;

		if(tmpRed < 0)
			tmpRed=0;

		if(tmpRed > 255)
			tmpRed=255;

		if(tmpGreen <0)
			tmpGreen=0;

		if(tmpGreen>255)
			tmpGreen=255;

		if(tmpBlue<0)
			tmpBlue=0;

		if(tmpBlue>255)
			tmpBlue=255;
	/*
	mettre les trois couleur dans le tableau tabRes
	*/
		tabRes[i].red=tmpRed;
		tabRes[i].green=tmpGreen;
		tabRes[i].blue=tmpBlue;

    }

}


void dissimulation(const pixel tab1[], const pixel tab2[],  pixel tab3[], unsigned int largeur, unsigned int hauteur, unsigned int nbBite)
{
    g_printf("#projv2.c:		in Dissimulation \n");
	g_printf("-->tab1	%p \n",tab1);
	g_printf("-->tab2	%p \n",tab2);
	g_printf("-->tab3	%p \n",tab3);
	g_printf("-->nbBite %u \n",nbBite);
	unsigned int i,j;
    unsigned char foo;
    //nbBite=8-nbBite;
    //g_printf("-->nbBite-8 %u \n",nbBite);
    for(i=0; i<(largeur*hauteur); i++)
    {
		/** réccupération des couleur RGB de l'image 1 et insérées
		dans la nouvelle image à créer */
		tab3[i].red     = tab1[i].red;
		tab3[i].green   = tab1[i].green;
		tab3[i].blue    = tab1[i].blue;
		/*nbBite represente les bites à exclure de l'image et garder les bites à tratier */
		for (j=nbBite; j<8 ; j++)
			{
			foo=getIemeBit(tab2[i].red, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].red),j-nbBite);
			else
				setIemeBit1(&(tab3[i].red),j-nbBite);
		// setIemeBit1(&(tab3[i].red),j);
		}
		/** nbBite represente les bites à exclure de l'image et garder les bites à tratier */
		for (j=nbBite; j<8 ; j++)
		{
			foo=getIemeBit(tab2[i].green, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].green),j-nbBite);
			else
				setIemeBit1(&(tab3[i].green),j-nbBite);
		}
		/* nbBite represente les bites à exclure de l'image et garder les bites à tratier */
		for (j=nbBite; j<8 ; j++)
		{
			foo=getIemeBit(tab2[i].blue, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].blue),j-nbBite);
			else
				setIemeBit1(&(tab3[i].blue),j-nbBite);
		}
	}
}


void extraction(const pixel tab1[],  pixel tab3[], unsigned int largeur, unsigned int hauteur, unsigned int nbBite)
{
   g_printf("#Extraction\n");
	unsigned int i,j;
	unsigned char foo;
	g_printf("-->nbBite %u \n",nbBite);
	//nbBite=8-nbBite;
	//g_printf("-->nbBite-8 %u \n",nbBite);

	for(i=0; i<(largeur*hauteur); i++)
    {
		/* nbBite represente les bites à exclure de l'image et garder les bites à tratier*/
		for (j=0; j< (8-nbBite) ; j++)
        {
			foo=getIemeBit(tab1[i].red, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].red),j+nbBite);
			else
				setIemeBit1(&(tab3[i].red),j+nbBite);
		}

		/* nbBite represente les bites à exclure de l'image et garder les bites à tratier*/
		for (j=0; j< (8-nbBite) ; j++)
        {
			foo=getIemeBit(tab1[i].green, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].green),j+nbBite);
			else
				setIemeBit1(&(tab3[i].green),j+nbBite);
		}

		/* nbBite represente les bites à exclure de l'image et garder les bites à tratier*/
		for (j=0; j< (8-nbBite) ; j++)
        {
			foo=getIemeBit(tab1[i].blue, j);
			if (foo == 0)
				setIemeBit0(&(tab3[i].blue),j+nbBite);
			else
				setIemeBit1(&(tab3[i].blue),j+nbBite);
		}
	}
}

void LireChaine(char chaine[], int size)
{
	g_printf("#LireChaine\n");
	fgets(chaine, size, stdin);
	chaine[strlen(chaine) - 1] = '\0';
}



void fskip(FILE *fp, int num_bytes)
{
	int i;
	for (i=0; i<num_bytes; i++)
	{
		fgetc(fp);
	}
}




void lireEntete(const char nomFichier[], unsigned int * largeur, unsigned int * hauteur)
{
 g_printf("#LireEntete\n");
  FILE * fic = fopen(nomFichier, "rb");
  if(fic == NULL)
  {
      g_printf("Impossible d’ouvrir le fichier\n");
      exit(EXIT_FAILURE);
  }
  unsigned short bitsparpixel = 0;
  unsigned int compression = 0, nbcolorsinpalette = 0, nbimportantcolors = 0;

  if (fgetc(fic)!='B' || fgetc(fic)!='M')
  {
    fclose(fic);
    fprintf(stderr, "%s n'est pas au format BMP.\n",nomFichier);
    exit(EXIT_FAILURE);
  }

  fskip(fic,16);
  fread(largeur, 4, 1, fic);
  fread(hauteur, 4, 1, fic);

  fskip(fic, 2); /* skipping the number of color planes (always 1) */
  fread(&bitsparpixel, 2, 1, fic);

  if(bitsparpixel != 24)
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le nombre de bits par pixel n'est pas 24, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }
  fread(&compression, 4, 1, fic);
  if(compression != 0)
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le mode de compression n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }

  fskip(fic,12);
  fread(&nbcolorsinpalette, 4, 1, fic);
  if(nbcolorsinpalette != 0)
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le nombre de couleurs dans la palette n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }

  fread(&nbimportantcolors, 4, 1, fic);
  if(nbimportantcolors != 0)
    {
      fclose(fic);
      fprintf(stderr, "Erreur: le nombre de couleurs importantes n'est pas 0, \n");
      fprintf(stderr, "ce format d'image n'est pas supporte par ce programme. \n");
      exit(EXIT_FAILURE);
    }


  fclose(fic);
}





void remplirTableauPixelsDepuisFichier(const char nomFichier[], pixel tab[],unsigned int largeur, unsigned int hauteur)
{
   g_printf("#projv2.c	Remplir Tableau Pixels Depuis Fichier\n");

   g_printf("-->fopen %s \n-->Pointeur %p\n",nomFichier,nomFichier);
  FILE * fic = fopen(nomFichier, "rb");
  if(fic == NULL)
  {
      perror("Erreur ");
      exit(EXIT_FAILURE);
  }
  unsigned int ligne, colonne, padding;

  fskip(fic, 54);
  for(ligne = 0; ligne < hauteur; ligne ++)
    {
      for (colonne = 0; colonne < largeur; colonne ++)
        {
          tab[(ligne*largeur) + colonne].red = fgetc(fic);
          tab[(ligne*largeur) + colonne].green = fgetc(fic);
          tab[(ligne*largeur) + colonne].blue = fgetc(fic);
        }

      /* Padding for 4 byte alignment */
      if( (3*largeur)%4 == 0) padding = 0;
      else padding = 4 - ((3*largeur)%4);
      fskip(fic, padding);
    }

  fclose(fic);
}



void ecrireFichier(const char nomFic[], const pixel tab[], unsigned int largeur, unsigned int hauteur)
{
   g_printf("#ecrireFichier\n");
	FILE * fic = fopen(nomFic, "wb");
	if(fic == NULL)
	{
		perror("Erreur ");
		exit(EXIT_FAILURE);
	}

  unsigned int monInt;
  unsigned short monShort;
  unsigned char monChar, i;
  unsigned int padding, ligne, colonne, index;

  char format[] = {'B', 'M'};
  unsigned int tailleFic = 54 + largeur*hauteur*3;


  fwrite(format, 1, 2, fic);

  // size of the file in bytes
  fwrite(&tailleFic, 4, 1, fic);

  // Unused, app specific
  monShort = 0;
  fwrite(&monShort, 2, 1, fic);
  fwrite(&monShort, 2, 1, fic);

  // Offset for pixel data
  monInt = 54;
  fwrite(&monInt, 4, 1, fic);

  // Nb of bytes in the header from this point
  monInt = 40;
  fwrite(&monInt, 4, 1, fic);

  fwrite(&largeur, 4, 1, fic);
  fwrite(&hauteur, 4, 1, fic);

  // Nb of color planes (always 1)
  monShort = 1;
  fwrite(&monShort, 2, 1, fic);

  // Nb of bits per pixel
  monShort = 24;
  fwrite(&monShort, 2, 1, fic);

  // Compression mode
  monInt = 0;
  fwrite(&monInt, 4, 1, fic);


  // Size of the raw BMP data (after this header), including padding
  if( (3*largeur)%4 == 0) padding = 0;
  else padding = 4 - ((3*largeur)%4);
  monInt = (largeur*3 + padding)*hauteur;
  fwrite(&monInt, 4, 1, fic);


  // Horiz and vertic resolutions (pixel per metre)
  monInt = 2835;
  fwrite(&monInt, 4, 1, fic);
  fwrite(&monInt, 4, 1, fic);


  // Numbers of colors in the palette & number of important colors
  monInt = 0;
  fwrite(&monInt, 4, 1, fic);
  fwrite(&monInt, 4, 1, fic);


  // Pixel data

  for(ligne = 0; ligne < hauteur; ligne ++)
    {
      for (colonne = 0; colonne < largeur; colonne ++)
        {
          index = largeur*ligne + colonne;
          fwrite(&tab[index].red, 1, 1, fic);
          fwrite(&tab[index].green, 1, 1, fic);
          fwrite(&tab[index].blue, 1, 1, fic);
        }

      // Padding for 4 byte alignment
      if( (3*largeur)%4 == 0) padding = 0;
      else padding = 4 - ((3*largeur)%4);
      monChar = 0;
      for (i = 0; i < padding; i++) fwrite(&monChar, 1, 1, fic);
    }

  fclose(fic);
}




unsigned char getIemeBit(unsigned char nombre, unsigned char numbit)
{

  return (nombre & (1 << numbit)) >> numbit;
}




void setIemeBit0(unsigned char * nombre, unsigned char numbit)
{

  *nombre = (*nombre) & (~(1 << numbit));
}



void setIemeBit1(unsigned char * nombre, unsigned char numbit)
{

  *nombre = (*nombre) | (1 << numbit);
}
